<?php


namespace app\astrologer\controller;


use app\common\cachemodel\ZlcrAstr;
use app\common\cachemodel\ZlcrAstrExercise;
use app\common\cachemodel\ZlcrAstrExerciseRecord;
use app\common\lib\Util;
use Exception;
use think\Env;
use think\response\Json;

class AstrExamine extends AstrAuth
{
    /**
     * 每关 每一题 分数
     * @var array
     */
    private $questionScore = [
        1 => 10,
        2 => 20,
    ];

    /**
     * 每关 通关 分数【总分】
     * @var array
     */
    private $levelSuccessScore = [
        1 => 350,// 答对35题第一关考试通过(ps:每题10分)
        2 => 0,
    ];

    private $levelRule = [
        1 => [
            'title' => '选择题考核规则',
            'list_content' => [
                '1、选择题考核共40题，分单选及多选，答对35题则考核成功进入笔试考核',
                '2、选择题考核每题回答时间为60秒，若超时则当前题默认0分，自动进入下一道题',
                '3、选择题考核总时长为1小时，若超过规定时间未提交则所有超时的题，自动设置为0分',
                '4、考核如不通过则从考试结束时间开始计算间隔24小时才可继续重新考核'
            ]
        ],
        2 => [
            'title' => '笔试题考核规则',
            'list_content' => [
                '1、占星师开始笔试考核后需要在特定星盘下回答指定问题，回复字数以及占星技法不限',
                '2、笔试考核总计时间为4小时，点击开始笔试考核后开始计时。若超过指定时间未提交则自动设置为0分',
                '3、提交回复后请占星师耐心等待，官方审核人员快马加鞭将在7个工作日内给予短信回复通知，请留意手机短信',
                '4、通过笔试考核后则可继续登录填写资料完成后续入驻流程'
            ]
        ]
    ];

    /**
     * 获取考试答题状态
     * @return Json
     * @throws Exception
     */
    public function getAssessmentData(): Json
    {
        $astrAnswerModel = new ZlcrAstrExerciseRecord();
        // 获取用户当前答题状态信息
        $astrAnswerInfo = $astrAnswerModel->getExerciseInfo($this->astrInfo['id'], 1);

        if ($astrAnswerInfo && (int)$astrAnswerInfo['status'] === 2 && $this->request->time() - $astrAnswerInfo['fail_time'] > 86400)
        {
            $astrAnswerInfo = null; // 失败24小时后允许重新考试
        }

        $resData = $this->getScore($astrAnswerInfo);

        return show(config('code.success'), '请求成功', $resData);
    }

    /**
     * 获取考试题目
     * @throws Exception
     */
    public function getExamineQuestion()
    {
        $index = input('index/d', 0);
        $option = trim(input('option/s', ''));

        $questionModel = new ZlcrAstrExercise();
        $astrAnswerModel = new ZlcrAstrExerciseRecord();

        // 获取用户当前答题状态信息
        $astrAnswerInfo = $astrAnswerModel->getExerciseInfo($this->astrInfo['id'], 1);

        if (Env::get('host.name') !== 'online')
        {
            $this->levelSuccessScore = [
                1 => 10,
                2 => 0,
            ];
        }

        if ($astrAnswerInfo)
        {
            $astrAnswerInfo['status'] = (int)$astrAnswerInfo['status'];
        }
        if ($astrAnswerInfo && $astrAnswerInfo['status'] === 2)
        {
            if ($this->request->time() - $astrAnswerInfo['fail_time'] > 86400)
            {
                $astrAnswerInfo = null; // 失败24小时后重新考试
                $astrAnswerModel->rmCacheData($this->astrInfo['id']);
            } else
            {
                return show(config('code.error'), '当前考核已结束');
            }
        }
        // 获取当前用户答题进度
        if (!$astrAnswerInfo)
        {   // 初始化答题进度
            // 获取第一关 随机35题
            $num_option_one = 35;
            $num_option_mul = 5;
            if (Env::get('host.name') !== 'online')
            {
                $num_option_one = 1;
                $num_option_mul = 5;
            }
            $questionIds = $questionModel->randomGetQuestionId(1, $num_option_one, 1);
            shuffle($questionIds);
            $Level2QuestionIds = $questionModel->randomGetQuestionId(2, $num_option_mul, 1);
            shuffle($Level2QuestionIds);
            $questionIds = array_merge($questionIds, $Level2QuestionIds);

            if (!$questionIds)
            {
                return show(config('code.error'), '服务异常；请稍后再试～');
            }

            $content1 = [
                'question' => $questionIds,
                'start_time' => $this->request->time(), // 开始答题时间
                'index' => 1, // 当前第几题
                'max_question' => $num_option_one + $num_option_mul,  // 总题目数
                'max_answer_time' => 60, // 最大答题时长
                'answer' => [] // 答案信息
            ];

            $cacheData = [
                'create_time' => $this->request->time(),
                'astr_id' => $this->astrInfo['id'],
                'content1' => \GuzzleHttp\json_encode($content1, JSON_UNESCAPED_UNICODE),
                'type' => 1,
                'content2' => '',
                'content3' => '',
                'content4' => '',
                'grade1' => 0,
                'grade2' => 0,
                'grade3' => 0,
                'grade4' => 0,
                'grade' => 0,
                'level' => 1,
                'status' => 1,
                'answer_time' => 0, //答题耗时 总时长
                'fail_time' => 0, // 失败时间
            ];

            $astrAnswerModel->setCacheData($cacheData, $this->astrInfo['id']);

            $questionId = $questionIds[$content1['index'] - 1];// 获取当前题目ID

            $resData = $this->getResultData($content1, $questionId, 10);
        } else
        {
            switch ($astrAnswerInfo['level'])
            {
                case 1:
                    // 提交答案 ｜ 获取题目 ｜ 结果
                    $content1 = \GuzzleHttp\json_decode($astrAnswerInfo['content1'], true);
                    if ($astrAnswerInfo['status'] === 2 || (isset($content1['answer_total_time']) && $content1['answer_total_time']))
                    {
                        $resData = [
                            'step' => 11,
                            'answer_right' => $content1['answer_right_num'],
                            'answer_wrong' => $content1['answer_wrong_num'],
                            'timeout_num' => $content1['answer_timeout_num'],
                            'max_question' => $content1['max_question'],
                            'isSuccessful' => false, // 是否通关
                            'tips' => '很遗憾您未能通过考核，请24小时后再次尝试'
                        ];
                        break;
                    }
                    if ($index && $option && $index <= $content1['index'])
                    {   // 提交答案
                        $res = $this->nextQuestion($content1, $index, $option, 10);
                        if ($res['updateCache'])
                        {   // 是否更新缓存
                            $astrAnswerInfo['content1'] = \GuzzleHttp\json_encode($res['content'], JSON_UNESCAPED_UNICODE);
                            if ($res['isOver'])
                            {
                                $score = $res['content']['answer_right_num'] * $this->questionScore[1];//每题5分
                                $astrAnswerInfo['grade1'] = $score; // 第一关分数
                                $astrAnswerInfo['grade'] += $score; // 总分数
                                $astrAnswerInfo['answer_time'] += $res['content']['answer_total_time']; // 答题总时长
                                if ($astrAnswerInfo['grade1'] < $this->levelSuccessScore[1]) // 总分
                                {   // 通关失败
                                    $astrAnswerInfo['status'] = 2;//挑战结束
                                    $astrAnswerInfo['fail_time'] = $this->request->time();
                                } else
                                {
                                    $astrAnswerInfo['level']++; // 升级下一关
                                }
                                unset($astrAnswerInfo['id']);
                                $id = $astrAnswerModel->insertGetId($astrAnswerInfo);

                                $astrAnswerInfo['id'] = $id;

                                $resData = [
                                    'step' => 11,
                                    'answer_right' => $res['content']['answer_right_num'],
                                    'answer_wrong' => $res['content']['answer_wrong_num'],
                                    'timeout_num' => $res['content']['answer_timeout_num'],
                                    'max_question' => $res['content']['max_question'],
                                    'isSuccessful' => $astrAnswerInfo['status'] === 1, // 是否通关
                                    'tips' => $astrAnswerInfo['status'] === 1 ? '恭喜您通过选择题考核，完成笔试考核即可入住平台' : '很遗憾您未能通过考核，请24小时后再次尝试'
                                ];
                                $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存
                                //发送钉钉通知
                                Util::sendZlcrMsg(7, ['占星师ID：' . $this->astrInfo['id'], '总计:' . $resData['max_question'] . ',答对:' . $resData['answer_right'] . ',答错:' . $resData['answer_wrong']], $this->headers['app-type']);
                                break;
                            }

                            $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存
                        }
                        $resData = $res['resData'];
                    } else
                    {   // 获取题目
                        $isNext = ($this->request->time() - $content1['start_time']) >= $content1['max_answer_time']; // 是否下一题
                        if ($isNext)
                        {   // 下一题
                            $res = $this->nextQuestion($content1, $content1['index'], '', 10);
                            if ($res['updateCache'])
                            {   // 是否更新缓存
                                $astrAnswerInfo['content1'] = \GuzzleHttp\json_encode($res['content'], JSON_UNESCAPED_UNICODE);
                                if ($res['isOver'])
                                {
                                    $score = $res['content']['answer_right_num'] * $this->questionScore[1];//每题5分
                                    $astrAnswerInfo['grade1'] = $score; // 第一关分数
                                    $astrAnswerInfo['grade'] += $score; // 总分数
                                    $astrAnswerInfo['answer_time'] += $res['content']['answer_total_time']; // 答题总时长

                                    if ($astrAnswerInfo['grade1'] < $this->levelSuccessScore[1]) // 总分
                                    {   // 通关失败
                                        $astrAnswerInfo['status'] = 2;//挑战结束
                                        $astrAnswerInfo['fail_time'] = $this->request->time();
                                    } else
                                    {
                                        $astrAnswerInfo['level']++; // 升级下一关
                                    }
                                    unset($astrAnswerInfo['id']);
                                    $id = $astrAnswerModel->insertGetId($astrAnswerInfo);

                                    $astrAnswerInfo['id'] = $id;

                                    $resData = [
                                        'step' => 11,
                                        'answer_right' => $res['content']['answer_right_num'],
                                        'answer_wrong' => $res['content']['answer_wrong_num'],
                                        'timeout_num' => $res['content']['answer_timeout_num'],
                                        'max_question' => $res['content']['max_question'],
                                        'isSuccessful' => $astrAnswerInfo['status'] === 1, // 是否通关
                                        'tips' => $astrAnswerInfo['status'] === 1 ? '恭喜您通过选择题考核，完成笔试考核即可入住平台' : '很遗憾您未能通过考核，请24小时后再次尝试'
                                    ];
                                    $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存
                                    //发送钉钉通知
                                    Util::sendZlcrMsg(7, ['占星师ID：' . $this->astrInfo['id'], '总计:' . $resData['max_question'] . ',答对:' . $resData['answer_right'] . ',答错:' . $resData['answer_wrong']], $this->headers['app-type']);
                                    break;
                                }

                                $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存
                            }
                            $resData = $res['resData'];
                        } else
                        {   // 当前题
                            $resData = $this->getResultData($content1, $content1['question'][$content1['index'] - 1], 10);
                        }
                    }
                    break;
                case 2:
                    if ($astrAnswerInfo['content2'])
                    {
                        $content2 = \GuzzleHttp\json_decode($astrAnswerInfo['content2'], true);
                        if ($content2['answer'])
                        {   // 提交过答案了
                            $resData = [
                                'step' => 21,
                                "index" => 1,//当前为第几题
                                "max_question" => 1,//总共有多少题
                                "tips" => '等待审核'
                            ];
                            break;
                        }
                        if ($option)
                        {   // 回答问题
                            $answerTime = $this->request->time() - $content2['start_time'];// 答题时间

                            if ($answerTime > ($content2['max_answer_time'] + 100))
                            { // 超时100秒提交 则无效
                                $option = '';
                            }
                            $content2['answer'] = [
                                'answer_time' => $answerTime > $content2['max_answer_time'] ? $content2['max_answer_time'] : $answerTime,
                                'option' => $option,
                                'start_time' => date('Y-m-d H:i:s', $content2['start_time']),
                            ];
                            $astrAnswerInfo['content2'] = \GuzzleHttp\json_encode($content2, JSON_UNESCAPED_UNICODE);
                            $astrAnswerInfo['answer_time'] += $content2['answer']['answer_time'];
                            $astrAnswerInfo['status'] = $option ? 4 : 2;  // 4=>待审核 ｜ 2=>失败
                            $astrAnswerInfo['fail_time'] = $content2['start_time'] + $content2['max_answer_time'];
                            // 更新
                            $astrAnswerModel->where('id', $astrAnswerInfo['id'])->update([
                                'update_time' => $this->request->time(),
                                'content2' => $astrAnswerInfo['content2'],
                                'answer_time' => $astrAnswerInfo['answer_time'],
                                'fail_time' => $astrAnswerInfo['fail_time'],
                                'status' => $astrAnswerInfo['status'],
                                'level' => $astrAnswerInfo['level']
                            ]);

                            if ($astrAnswerInfo['status'] === 4)
                            {
                                (new ZlcrAstr())->UpdateData($this->astrInfo['id'], ['id' => $this->astrInfo['id']], ['check_status' => 11]);
                            }

                            $resData = [
                                'step' => 21,
                                "index" => 1,//当前为第几题
                                "max_question" => 1,//总共有多少题
                                "tips" => $astrAnswerInfo['status'] === 2 ? '很遗憾您未能通过考核，请24小时后再次尝试' : '等待审核'
                            ];

                            $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存

                            //发送钉钉通知
                            Util::sendZlcrMsg(1, ['请尽快审核'], $this->headers['app-type']);
                            break;
                        }

                        // 获取问题
                        $isNext = ($this->request->time() - $content2['start_time']) >= $content2['max_answer_time']; // 是否下一题
                        if ($isNext)
                        {
                            $content2['answer'] = [
                                'answer_time' => $content2['max_answer_time'],
                                'option' => '',
                                'start_time' => date('Y-m-d H:i:s', $content2['start_time']),
                            ];
                            $astrAnswerInfo['content2'] = \GuzzleHttp\json_encode($content2, JSON_UNESCAPED_UNICODE);
                            $astrAnswerInfo['answer_time'] += $content2['max_answer_time'];
                            $astrAnswerInfo['status'] = 2;
                            $astrAnswerInfo['fail_time'] = $content2['start_time'] + $content2['max_answer_time'];
                            // 更新
                            $astrAnswerModel->where('id', $astrAnswerInfo['id'])->update([
                                'update_time' => $this->request->time(),
                                'content2' => $astrAnswerInfo['content2'],
                                'answer_time' => $astrAnswerInfo['answer_time'],
                                'fail_time' => $astrAnswerInfo['fail_time'],
                                'status' => $astrAnswerInfo['status'],
                                'level' => $astrAnswerInfo['level']
                            ]);
                            $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存

                            $resData = [
                                'step' => 21,
                                "index" => 1,//当前为第几题
                                "max_question" => 1,//总共有多少题
                                "tips" => '很遗憾您未能通过考核，请24小时后再次尝试'
                            ];
                            break;
                        }
                        $resData = $this->getResultData($content2, $content2['question'][$content2['index'] - 1], 20);
                    } else
                    {
                        if ($astrAnswerInfo['status'] === 2 || $astrAnswerInfo['grade1'] < $this->levelSuccessScore[1]) // 当前关卡分数满足条件
                        {
                            return show(config('code.error'), '当前考核已结束');
                        }
                        // 初始化第二关答题进度
                        // 获取第二关 随机1题
                        $questionIds = $questionModel->randomGetQuestionId(3, 1, 1);

                        if (!$questionIds)
                        {
                            return show(config('code.error'), '服务异常；请稍后再试～');
                        }

                        $content2 = [
                            'question' => $questionIds,
                            'start_time' => $this->request->time(), // 开始答题时间
                            'index' => 1, // 当前第几题
                            'max_question' => 1,  // 总题目数
                            'max_answer_time' => 14400, // 最大答题时长 4小时
                            'answer' => [] // 答案信息
                        ];
                        $questionId = $questionIds[$content2['index'] - 1];// 获取当前题目ID

                        $astrAnswerInfo['content2'] = \GuzzleHttp\json_encode($content2, JSON_UNESCAPED_UNICODE);
                        $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存

                        $resData = $this->getResultData($content2, $questionId, 20);
                    }
                    break;
                default:
                    return show(config('code.error'), '服务异常；请稍后再试～');
            }
        }

        // 返回结果
        return show(config('code.success'), '请求成功', $resData);
    }

    /**
     * 返回题目信息
     * @param $content array 问题信息
     * @param $qid int  问题ID
     * @param $step int 当前进度 10=>第一关进行中 20=>第二关进行中 30=>第三关进行中 40=>第四关进行中
     * @return array
     * @throws Exception
     */
    private function getResultData(array $content, int $qid, int $step): array
    {
        $questionInfo = (new ZlcrAstrExercise())->getInfoById($qid, ['title', 'option_a', 'option_b', 'option_c', 'option_d', 'title_img', 'option_type']);

        $endTime = $content['max_answer_time'] ? $content['max_answer_time'] - ($this->request->time() - $content['start_time']) : 0;
        $tips = '';
        if ((int)$questionInfo['option_type'] === 3)
        {
//            $times = $this->request->time() + $endTime;
//            $tips = date('Y.m.d H:i:s', $times);
            $tips = '等待审核';
            $astro = [
                'is_merage' => false,
                'id' => $qid
            ];
        } else
        {
            $topicOption = [
                [
                    'text' => htmlspecialchars_decode($questionInfo['option_a']),
                    'value' => 'A'
                ],
                [
                    'text' => htmlspecialchars_decode($questionInfo['option_b']),
                    'value' => 'B'
                ],
                [
                    'text' => htmlspecialchars_decode($questionInfo['option_c']),
                    'value' => 'C'
                ],
                [
                    'text' => htmlspecialchars_decode($questionInfo['option_d']),
                    'value' => 'D'
                ]
            ];
        }

        return [
            'step' => $step,
            'index' => (int)$content['index'],
            'max_question' => (int)$content['max_question'],
            'end_time' => $endTime,
            'title' => htmlspecialchars_decode($questionInfo['title']),
            'topic_option' => $topicOption ?? null,
            'astro' => $astro ?? null,
            'option_type' => (int)$questionInfo['option_type'],
            'title_img' => $questionInfo['title_img'] ? Env::get('host.photo') . $questionInfo['title_img'] : '',
            'tips' => $tips
        ];
    }

    /**
     * 提交答案 进入下一题 ｜ 计算结果
     * @param $content array 关卡内容
     * @param $index int  当前题目
     * @param $option string 答案
     * @param $setp int 当前进度 10=>第一关进行中 20=>第二关进行中 30=>第三关进行中 40=>第四关进行中
     * @return array
     * @throws Exception
     */
    private function nextQuestion(array $content, int $index, string $option, int $setp): array
    {
        if ($index < $content['index'])
        {  // 可能情况  网络异常或其他 回答上一题答案
            $updateCache = false;
            if ($index === ($content['index'] - 1) && (($answerTime = $this->request->time() - strtotime($content['answer'][$index]['start_time'])) < ($content['max_answer_time'] + 10)))
            { // 在上一题允许范围内 则 为有效答题
                $content['answer'][$index] = [
                    'answer_time' => $answerTime > $content['max_answer_time'] ? $content['max_answer_time'] : $answerTime, // 当前问题消耗时长
                    'option' => $option, // 答案
                    'start_time' => $content['answer'][$index]['start_time']
                ];
            } else
            { // 无效答题
                if ($content['max_answer_time'] > 0 && ($this->request->time() - $content['start_time']) >= $content['max_answer_time'])
                { // 当前答案回答时间 也过期
                    $content['answer'][$content['index']] = [
                        'answer_time' => $content['max_answer_time'], // 当前问题消耗时长
                        'option' => '', // 答案
                        'start_time' => date('Y-m-d H:i:s', $content['start_time'])
                    ];
                    $content['index']++;
                    $updateCache = true;
                    if ($content['index'] > $content['max_question'])
                    { // 计算结果 | 返回答题信息
                        // 计算答题信息
                        $content = $this->totalScore($content);
                        return [
                            'content' => $content,
                            'updateCache' => true,
                            'isOver' => true,
                        ];
                    }
                    $content['start_time'] = $this->request->time();
                }
            }

            return [
                'content' => $content,
                'updateCache' => $updateCache,
                'isOver' => false,
                'resData' => $this->getResultData($content, $content['question'][$content['index'] - 1], $setp)
            ];
        }

        // 正常提交答案
        $answerTime = $this->request->time() - $content['start_time'];
        if ($content['max_answer_time'] > 0 && (!$option || ($answerTime > ($content['max_answer_time'] + 10))))
        {   // 无效答题
            $option = '';
        }
        $content['answer'][$index] = [
            'answer_time' => $answerTime > $content['max_answer_time'] ? $content['max_answer_time'] : $answerTime, // 当前问题消耗时长
            'option' => $option, // 答案
            'start_time' => date('Y-m-d H:i:s', $content['start_time'])
        ];

        if ($content['index'] >= $content['max_question'])
        { // 计算结果 得分
            // 计算答题信息
            $content = $this->totalScore($content);
            return [
                'content' => $content,
                'updateCache' => true,
                'isOver' => true,
            ];
        }

        // 返回下一题
        $content['index']++;
        $content['start_time'] = $this->request->time();
        return [
            'content' => $content,
            'updateCache' => true,
            'isOver' => false,
            'resData' => $this->getResultData($content, $content['question'][$content['index'] - 1], $setp)
        ];
    }

    /**
     * 计算正确结果
     * @param $content
     * @return array
     * @throws Exception
     */
    private function totalScore(array $content): array
    {
        $questionInfo = (new ZlcrAstrExercise())->batchGetInfoByIds($content['question'], ['answer', 'option_type']);

        $answerTotalTime = 0; // 答题总时长
        $answerRight = 0;// 正确答题数
        $timeOutNum = 0;// 超时数量
        $answerWrong = 0;// 错误答题数
        $answerRightQuestion = [];// 回答正确的题目 第几题 题目从1开始
        for ($i = 1; $i <= $content['max_question']; $i++)
        {
            if (isset($content['answer'][$i]) && $content['answer'][$i]['option'])
            {   // 如果当前题目回答了
                // 判断是否正确
                if ($questionInfo[$content['question'][$i - 1]]['option_type'] == 1)
                {
                    $answer = strtoupper($content['answer'][$i]['option']);
                    $questionAnswer = strtoupper(trim($questionInfo[$content['question'][$i - 1]]['answer'])); // 问题答案
                } else
                {
                    $answer = explode(',', strtoupper($content['answer'][$i]['option'])); // 答案
                    $questionAnswer = explode(',', strtoupper(trim($questionInfo[$content['question'][$i - 1]]['answer']))); // 问题答案
                    asort($answer);
                    asort($questionAnswer);
                    $answer = array_values($answer);
                    $questionAnswer = array_values($questionAnswer);
                }
                if ($answer === $questionAnswer)
                {
                    $answerRight++;
                    $answerRightQuestion[] = $i;// 当前第几题回答正确
                } else
                {
                    $answerWrong++;
                }
                $answerTotalTime += $content['answer'][$i]['answer_time'];//答题时长
            } else
            {   // 当前题目超时未回答
                $timeOutNum++;
                $answerTotalTime += $content['max_answer_time']; // 答题时长
            }
        }

        $content['answer_total_time'] = $answerTotalTime; // 答题总时长
        $content['answer_right_num'] = $answerRight;    // 答对的题目数量
        $content['answer_timeout_num'] = $timeOutNum;    // 超时数量
        $content['answer_wrong_num'] = $answerWrong;    // 错误答题数
        $content['answer_right_question'] = $answerRightQuestion; // 答对的题目

        return $content;
    }

    /**
     * 查看考试结果
     * @param array $astrAnswerInfo
     * @return array
     * @throws Exception
     */
    private function getScore($astrAnswerInfo = []): array
    {
        if ($astrAnswerInfo)
        {
            switch ($astrAnswerInfo['level'])
            {
                case 1:
                    if ((int)$astrAnswerInfo['status'] === 2)
                    {   // 未通过
                        $nextTime = ($this->request->time() + 86400) - $astrAnswerInfo['fail_time']; // 距离下次考核时间
                        $status = 1;
                        $h = ceil($nextTime / 3600);
                        $tips = '未通过，' . ($h > 24 ? 24 : $h) . '个小时后才允许再次考试';
                    } else
                    {   // 进行中
                        $content1 = \GuzzleHttp\json_decode($astrAnswerInfo['content1'], true);
                        if ($this->request->time() - $content1['start_time'] >= 3600)   // 超时1小时
                        {   // 任务失败
                            $astrAnswerInfo['answer_time'] += $content1['max_answer_time'];
                            $astrAnswerInfo['status'] = 2;
                            $astrAnswerInfo['fail_time'] = $content1['start_time'] + 3600;  // 任务失败时间
                            // 更新
                            $astrAnswerModel = new ZlcrAstrExerciseRecord();
                            if (isset($astrAnswerInfo['id']))
                            {
                                $astrAnswerModel->where('id', $astrAnswerInfo['id'])->update([
                                    'update_time' => $this->request->time(),
                                    'content1' => $astrAnswerInfo['content1'],
                                    'answer_time' => $astrAnswerInfo['answer_time'],
                                    'fail_time' => $astrAnswerInfo['fail_time'],
                                    'status' => $astrAnswerInfo['status'],
                                ]);
                            } else
                            {
                                $id = $astrAnswerModel->insertGetId($astrAnswerInfo);
                                $astrAnswerInfo['id'] = $id;
                            }

                            $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存

                            $tim = $astrAnswerInfo['fail_time'] + 86400 - $this->request->time();
                            // 判断失败时间距离现在是否满足24小时
                            if ($tim > 0)
                            {   // 不满足24小时
                                $status = 1;
                                $h = ceil($tim / 3600);
                                $tips = '未通过，' . ($h > 24 ? 24 : $h) . '个小时后才允许再次考试';
                            } else
                            {   // 满足24小时 重新从头开始考试
                                return [
                                    'msg_title' => '恭喜您注册成功',
                                    'msg_des' => '现在开始选择题、笔试题考核，成功后即可入驻准了占星平台',
                                    'next_time' => 0,
                                    'list' => [
                                        [
                                            'id' => 1,
                                            'title' => '选择题',
                                            'status' => 0,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                                            'tips' => '',
                                            'content' => $this->levelRule[1]
                                        ],
                                        [
                                            'id' => 2,
                                            'title' => '笔试题',
                                            'status' => -1,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                                            'tips' => '',
                                            'content' => $this->levelRule[2],
                                        ]
                                    ],
                                ];
                            }
                        } else
                        {
                            $status = 3;
                            $tips = '进行中';
                        }
                    }

                    $list = [
                        [
                            'id' => 1,
                            'title' => '选择题',
                            //已通过
                            'status' => $status,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过 3=>进行中
                            'tips' => $tips,
                            'content' => $this->levelRule[1]
                        ],
                        [
                            'id' => 2,
                            'title' => '笔试题',
                            //可以考试
                            'status' => -1,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                            'tips' => '',
                            'content' => $this->levelRule[2],
                        ]
                    ];
                    break;
                default: // 笔试
                    // 判断 是否在进行中
                    if ($astrAnswerInfo['content2'])
                    {   // 进行中
                        // 判断任务是否失败
                        $content2 = \GuzzleHttp\json_decode($astrAnswerInfo['content2'], true);
                        if ($content2['answer'])
                        {   // 已经回答过了 等待审核
                            if ((int)$astrAnswerInfo['status'] === 2)
                            {
                                $nextTime = ($this->request->time() + 86400) - $astrAnswerInfo['fail_time']; // 距离下次考核时间
                                $status = 1;
                                $h = ceil($nextTime / 3600);
                                $tips = '未通过，' . ($h > 24 ? 24 : $h) . '个小时后才允许再次考试';
                            } else
                            {
                                $status = 4;
                                $tips = '等待审核';
                            }
                        } else
                        {
                            // 判断任务是否已过期
                            if (($this->request->time() - $content2['start_time']) >= $content2['max_answer_time'])
                            {   // 任务过期 将任务状态改为过期
                                $content2['answer'] = [
                                    'answer_time' => $content2['max_answer_time'],
                                    'option' => '',
                                    'start_time' => date('Y-m-d H:i:s', $content2['start_time']),
                                ];
                                $astrAnswerInfo['content2'] = \GuzzleHttp\json_encode($content2, JSON_UNESCAPED_UNICODE);
                                $astrAnswerInfo['answer_time'] += $content2['max_answer_time'];
                                $astrAnswerInfo['status'] = 2;
                                $astrAnswerInfo['fail_time'] = $content2['start_time'] + $content2['max_answer_time'];
                                // 更新
                                $astrAnswerModel = new ZlcrAstrExerciseRecord();
                                $astrAnswerModel->where('id', $astrAnswerInfo['id'])->update([
                                    'update_time' => $this->request->time(),
                                    'content2' => $astrAnswerInfo['content2'],
                                    'answer_time' => $astrAnswerInfo['answer_time'],
                                    'fail_time' => $astrAnswerInfo['fail_time'],
                                    'status' => $astrAnswerInfo['status'],
                                    'level' => $astrAnswerInfo['level']
                                ]);
                                $astrAnswerModel->setCacheData($astrAnswerInfo, $this->astrInfo['id']); // 更新缓存

                                $tim = $astrAnswerInfo['fail_time'] + 86400 - $this->request->time();
                                // 判断失败时间距离现在是否满足24小时
                                if ($tim > 0)
                                {   // 不满足24小时

                                    $status = 1;
                                    $h = ceil($tim / 3600);
                                    $tips = '未通过，' . ($h > 24 ? 24 : $h) . '个小时后才允许再次考试';
                                } else
                                {   // 满足24小时 重新从头开始考试
                                    return [
                                        'msg_title' => '恭喜您注册成功',
                                        'msg_des' => '现在开始选择、笔试考核，成功后即可入驻准了占星平台',
                                        'next_time' => 0,
                                        'list' => [
                                            [
                                                'id' => 1,
                                                'title' => '选择题',
                                                'status' => 0,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                                                'tips' => '',
                                                'content' => $this->levelRule[1]
                                            ],
                                            [
                                                'id' => 2,
                                                'title' => '笔试题',
                                                'status' => -1,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                                                'tips' => '',
                                                'content' => $this->levelRule[2],
                                            ]
                                        ],
                                    ];
                                }
                            } else
                            {   // 还未过期
                                $status = 3;
                                $tips = '进行中';
                            }
                        }
                    } else
                    {   // 未开始 待考核
                        $status = 0;
                        $tips = '';
                    }

                    $list = [
                        [
                            'id' => 1,
                            'title' => '选择题',
                            //已通过
                            'status' => 2,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过 3=>进行中
                            'tips' => '已通过',
                            'content' => $this->levelRule[1]
                        ],
                        [
                            'id' => 2,
                            'title' => '笔试题',
                            //可以考试
                            'status' => $status,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过 3=>进行中 4=>待审核
                            'tips' => $tips,
                            'content' => $this->levelRule[2],
                        ]
                    ];
            }

            return [
                'msg_title' => '恭喜您注册成功',
                'msg_des' => '现在开始选择、笔试考核，成功后即可入驻准了占星平台',
                'list' => $list,
            ];
        }

        return [
            'msg_title' => '恭喜您注册成功',
            'msg_des' => '现在开始选择、笔试考核，成功后即可入驻准了占星平台',
            'list' => [
                [
                    'id' => 1,
                    'title' => '选择题',
                    'status' => 0,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                    'tips' => '',
                    'content' => $this->levelRule[1]
                ],
                [
                    'id' => 2,
                    'title' => '笔试题',
                    'status' => -1,// -1=>不可以考试（前端不可点击）、0=>可以考试（前端可以点击）、1=>未通过、2=>已通过
                    'tips' => '',
                    'content' => $this->levelRule[2],
                ]
            ],
        ];
    }

    /**
     * 获取平台培训考核题目
     */
    public function platformTest()
    {
        $vi = input('vi/s', 0);
        $index = input('index/d', 0);
        $option = trim(input('option/s', ''));

        $cacheId = $this->astrInfo['id'] . ':' . $vi;
        $questionModel = new ZlcrAstrExercise();
        $astrAnswerModel = new ZlcrAstrExerciseRecord();
        // 获取用户当前答题状态信息
        $astrAnswerInfo = $astrAnswerModel->getPlatformExerInfo($cacheId);
        if ($astrAnswerInfo && (int)$astrAnswerInfo['status'] === 2)
        {
            $astrAnswerInfo = null;
        }
// 获取当前用户答题进度
        if (!$astrAnswerInfo)
        {   // 初始化答题进度
            // 获取第一关 随机20题
            $questionIds = $questionModel->randomGetQuestionId(1, 10, 2);
            shuffle($questionIds);

            if (!$questionIds)
            {
                return show(config('code.error'), '服务异常；请稍后再试～');
            }

            $content1 = [
                'question' => $questionIds,
                'start_time' => $this->request->time(), // 开始答题时间
                'index' => 1, // 当前第几题
                'max_question' => 10,  // 总题目数
                'must_right_num' => 10, // 考核通过需要答对的题目数
                'max_answer_time' => 0, // 最大答题时长
                'answer' => [] // 答案信息
            ];

            $cacheData = [
                'create_time' => $this->request->time(),
                'astr_id' => $this->astrInfo['id'],
                'content1' => \GuzzleHttp\json_encode($content1, JSON_UNESCAPED_UNICODE),
                'status' => 1,
                'grade1' => 0,
            ];

            $astrAnswerModel->setPlatformExerInfoCache($cacheId, $cacheData);

            $questionId = $questionIds[$content1['index'] - 1];// 获取当前题目ID

            $resData = $this->getResultData($content1, $questionId, 10);
        } else
        {
            // 提交答案 ｜ 获取题目 ｜ 结果
            $content1 = \GuzzleHttp\json_decode($astrAnswerInfo['content1'], true);

            if ($index && $option && $index <= $content1['index'])
            {   // 提交答案
                $res = $this->nextQuestion($content1, $index, $option, 10);
                if ($res['updateCache'])
                {   // 是否更新缓存
                    $astrAnswerInfo['content1'] = \GuzzleHttp\json_encode($res['content'], JSON_UNESCAPED_UNICODE);
                    if ($res['isOver'])
                    {
                        if ($res['content']['answer_right_num'] >= $res['content']['must_right_num']) // 判断题目答对数量
                        {   // 考核通过 更新占星师认证状态
                            (new ZlcrAstr())->save(['check_status' => 40, 'update_time' => $this->request->time()], ['id' => $this->astrInfo['id']]);
                        } else
                        {   // 通关失败
                            $astrAnswerInfo['status'] = 2;//挑战结束
                        }

                        $astrAnswerModel->setPlatformExerInfoCache($cacheId, $astrAnswerInfo); // 更新缓存

                        //test
//                        $astrAnswerInfo['status'] = 1;
                        //test

                        $res['resData'] = [
                            'is_over' => true,
                            'isSuccessful' => (int)$astrAnswerInfo['status'] === 1, // 是否通关
                            'tips' => (int)$astrAnswerInfo['status'] === 1 ? '恭喜您通过当前考核' : '很遗憾您未能通过当前考核'
                        ];
                    }

                    $astrAnswerModel->setPlatformExerInfoCache($cacheId, $astrAnswerInfo); // 更新缓存
                }
                $resData = $res['resData'];
            } else
            {   // 获取题目
                $resData = $this->getResultData($content1, $content1['question'][$content1['index'] - 1], 10);
            }
        }

        return show(200, '请求成功', $resData);
    }
}
